library lib_module_manager;

import 'package:flutter/foundation.dart';
import 'package:lib_module_manager/module_manager/handler.dart';
import 'package:lib_module_manager/module_manager/module.dart';
import 'package:lib_module_manager/module_manager/widgets/page_widget.dart';
import 'package:lib_service/router_service.dart';

class ModuleManager {
  static final ModuleManager instance = ModuleManager._internal();

  late final Map<String, CreateModule> _createModuleFuncs = {};

  late final List<Module> _modules = [];

  ModuleManager._internal();

  void registerModule(
      {required String type, required CreateModule createModule}) {
    _createModuleFuncs[type] = createModule;
  }

  Module? getModule({required String type, String? id}) {
    final int index = _modules
        .indexWhere((element) => element.type == type && element.id == id);
    if (index != -1) {
      return _modules[index];
    }

    CreateModule? createModule = _createModuleFuncs[type];
    if (createModule == null) {
      return null;
    }

    final Module? module = createModule(id: id);
    if (module != null) {
      _modules.add(module);
    }

    return module;
  }

  void removeModule({required String type, String? id}) {
    _modules.removeWhere((element) => element.type == type && element.id == id);
    if (kDebugMode) {
      print("Remove module type: $type, id: ${id ?? ""}");
      print("Module count: ${_modules.length}");
    }
  }

  PageWidget? pageWidget({required String url, Map<String, dynamic>? params}) {
    Uri uri = Uri.parse(url);

    if (uri.pathSegments.length < 2) {
      return null;
    }

    String moduleType = uri.pathSegments[0];
    String? moduleId = uri.queryParameters['moduleId'];
    String pageType = uri.pathSegments[1];
    String? pageId = uri.queryParameters['pageId'];

    return _pageWidget(
      moduleType: moduleType,
      moduleId: moduleId,
      pageType: pageType,
      pageId: pageId,
      params: params,
    );
  }

  PageWidget? _pageWidget({
    required String moduleType,
    String? moduleId,
    required String pageType,
    String? pageId,
    Map<String, dynamic>? params,
  }) {
    return getModule(type: moduleType, id: moduleId)
        ?.getPage(type: pageType, id: pageId, params: params)
        ?.pageWidget;
  }

  Future<RouteCompletion> handle({
    required String url,
    Map<String, dynamic>? params,
  }) async {
    Uri uri = Uri.parse(url);

    if (uri.host != 'handler') {
      return RouteCompletion(result: RouteResult.error, param: null);
    }

    if (uri.pathSegments.length < 2) {
      return RouteCompletion(result: RouteResult.error, param: null);
    }

    String moduleType = uri.pathSegments.first;
    String? moduleId = uri.queryParameters['moduleId'];
    String handlerType = uri.pathSegments[1];

    Map<String, dynamic>? paramDic;
    if (params != null) {
      paramDic = Map.from(params);
      paramDic.addAll(uri.queryParameters);
    } else {
      paramDic = uri.queryParameters.isEmpty ? null : uri.queryParameters;
    }

    Handler? handler = _handler(
      moduleType: moduleType,
      moduleId: moduleId,
      handlerType: handlerType,
    );

    if (handler == null) {
      return RouteCompletion(result: RouteResult.error, param: null);
    }

    return handler.handle(params: paramDic);
  }

  Handler? _handler(
      {required String moduleType,
      String? moduleId,
      required String handlerType}) {
    return getModule(type: moduleType, id: moduleId)
        ?.getHandler(type: handlerType);
  }
}
